import { ref } from "vue"
import { CountToSeparator } from "../../../../types/tn-count-to"

type CountToAnimationFunction = (time: number) => void

/**
 * 滚动动画执行函数
 */
export default function useCountTo(endFn: Function) {

  // 分隔符配置
  let separator: CountToSeparator = {}
  // 保留的小数位
  let decimals: number = 0
  // 动画持续时间
  let duration: number = 0
  // 开始值
  let startVal: number = 0
  // 结束值
  let endVal: number = 0
  // 标记是往下计算还是往上计算
  let countDown: boolean = false

  // 当前计算数值
  let currentValue:number = 0
  // 显示的数值
  let displayValue = ref<string>('')

  // 帧动画定时器
  let frameTimer: number | null = null
  // 动画开始执行时间
  let animationStartTime: number = 0
  // 最后执行动画的时间
  let animationLastTime: number = 0
  // 剩余执行时间
  let remainingTime: number = 0

  // 更新开始、结束的值
  const updateValue = (_startVal: number, _endVal: number, autoplay: boolean = false) => {
    startVal = _startVal
    endVal = _endVal
    countDown = _startVal > _endVal
    if (autoplay) startAnimation()
  }

  // 更新配置
  const updateOption = (_separator: CountToSeparator, _decimals: number, _duration: number) => {
    separator = _separator
    decimals = _decimals
    duration = _duration
  }

  // 开始执行动画
  const startAnimation = () => {
    _clearAnimationFrame()
    animationStartTime = 0
    animationLastTime = 0
    _createAnimationFrame(_countAnimation)
  }
  // 暂停动画
  const pauseAnimation = () => {
    _clearAnimationFrame()
  }
  // 恢复动画
  const resumeAnimation = () => {
    if (currentValue === endVal) return
    _clearAnimationFrame()
    duration = remainingTime
    startVal = currentValue
    animationStartTime = 0
    _createAnimationFrame(_countAnimation)
  }

  // 执行动画
  const _countAnimation: CountToAnimationFunction = (time: number) => {
    if (!animationStartTime) animationStartTime = time
    // 当前执行的时间进度
    const progress = time - animationStartTime
    // 剩余执行时间
    remainingTime = duration - progress
    if (countDown) {
      currentValue = startVal - _easingFn(progress, 0, startVal - endVal, duration)
      currentValue = currentValue < endVal ? endVal : currentValue
    } else {
      currentValue = _easingFn(progress, startVal, endVal - startVal, duration)
      currentValue = currentValue > endVal ? endVal : currentValue
    }
    displayValue.value = _formatNumber(currentValue)
    if (progress < duration) {
      _createAnimationFrame(_countAnimation)
    } else {
      endFn && endFn()
    }
  }

  // 使用定时器实现帧动画
  // 创建帧动画定时器
  const _createAnimationFrame = (fn: CountToAnimationFunction) => {
    const currentTime = new Date().getTime()
    // 使用setTimeout实现60帧的效果
    const durationTime = Math.max(0, 16 - (currentTime - animationLastTime))
    frameTimer = setTimeout(() => {
      fn && fn(currentTime + durationTime)
    }, durationTime);
    animationLastTime = currentTime + durationTime
  }
  // 清除帧动画定时器
  const _clearAnimationFrame = () => {
    if (frameTimer !== null) {
      clearTimeout(frameTimer)
      frameTimer = null
    }
  }
  // 计算缓动时间
  const _easingFn = (t: number, b: number, c: number, d: number) => {
    return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
  }

  // 格式化显示的数值
  const _formatNumber = (number: number): string => {
    const reg = /(\d+)(\d{3})/
    const numberStr = number.toFixed(decimals)
    const numberArr = numberStr.split('.')
    let number1 = numberArr[0]
    let number2 = numberArr.length > 1 ? separator.decimal + numberArr[1] : ''

    if (separator?.thousandths && isNaN(parseFloat(separator.thousandths))) {
      while (reg.test(number1)) {
        number1 = number1.replace(reg, '$1' + separator.thousandths + '$2')
      }
    }
    return number1 + number2
  }

  return {
    displayValue,
    updateValue,
    updateOption,
    startAnimation,
    pauseAnimation,
    resumeAnimation
  }
}